home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / VolumeFog / main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  39.8 KB  |  1,144 lines

  1. //-----------------------------------------------------------------------------
  2. // File: main.cpp
  3. //
  4. // Desc: Example code showing a technique for rendering volumetric fog in D3D.
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <tchar.h>
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include <d3dx8.h>
  13. #include "d3dapp.h"
  14. #include "d3dfont.h"
  15. #include "dxutil.h"
  16.  
  17. #define RENDERTARGSIZE 512
  18.  
  19.  
  20. // Maintains a set of triangles - its vertices and indices
  21. struct TRIANGLESET
  22. {
  23.     LPDIRECT3DINDEXBUFFER8 pIndexBuffer;
  24.     LPDIRECT3DVERTEXBUFFER8 pVertexBuffer;
  25.     DWORD dwNumVertices;
  26.     DWORD dwNumTriangles;
  27.     D3DXVECTOR3 Center;
  28.     FLOAT fRadius;
  29. };
  30.  
  31. struct FILEVERTEX
  32. {
  33.     FLOAT x,y,z;
  34.     FLOAT nx,ny,nz;
  35. };
  36.  
  37. #define D3DFVF_FILEVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL)
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Name: class CMyD3DApplication
  42. // Desc: Application class. The base class (CD3DApplication) provides the 
  43. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  44. //       adds functionality specific to this sample program.
  45. //-----------------------------------------------------------------------------
  46. class CMyD3DApplication : public CD3DApplication
  47. {
  48. protected:
  49.     D3DXMATRIX  m_matObject;
  50.     D3DXMATRIX  m_matView;
  51.     D3DXMATRIX  m_matProj;
  52.     D3DXMATRIX  m_matShadObject;
  53.  
  54.     BOOL m_bInsideFog;
  55.     BOOL m_bUsePicShader;
  56.     BOOL m_bDrawHelp;
  57.  
  58.     LPDIRECT3DVERTEXBUFFER8 m_pScreenVertBuf;
  59.     LPDIRECT3DVERTEXBUFFER8 m_pScreenVertBuf2;
  60.     LPDIRECT3DSURFACE8 m_pOldRenderTarget;
  61.     LPDIRECT3DSURFACE8 m_pOldStencilZ;
  62.     LPDIRECT3DSURFACE8 m_pTargetZ;
  63.  
  64.     TRIANGLESET m_FogVolume;
  65.     TRIANGLESET m_MeshShaderObject;
  66.  
  67.     BYTE            m_bKey[256];
  68.     D3DXVECTOR3     m_vVelocity;
  69.     FLOAT           m_fYawVelocity;
  70.     FLOAT           m_fPitchVelocity;
  71.     D3DXMATRIX      m_matOrientation;
  72.     D3DXVECTOR3     m_vPosition;
  73.     FLOAT           m_fYaw;
  74.     FLOAT           m_fPitch;
  75.  
  76.     LPDIRECT3DTEXTURE8 m_pBackFogDist;
  77.     LPDIRECT3DTEXTURE8 m_pFrontFogDist;
  78.     LPDIRECT3DTEXTURE8 m_pSceneDist;
  79.     LPDIRECT3DTEXTURE8 m_pTempDist;
  80.  
  81.     LPDIRECT3DTEXTURE8 m_pStepTexture;
  82.     
  83.     LPD3DXBUFFER  m_pCodeFogShader;
  84.     LPD3DXBUFFER  m_pCodeFogShader2;
  85.     LPD3DXBUFFER  m_pCodeSubPicShader;
  86.  
  87.     DWORD         m_dwFogShader;
  88.     DWORD         m_dwFogShader2;
  89.     DWORD         m_dwSubPicShader;
  90.  
  91.     LPD3DXMESH    m_pMeshObject;
  92.      
  93.     CD3DFont*     m_pFont;
  94.     CD3DFont*     m_pFontSmall;
  95.  
  96. public:
  97.     CMyD3DApplication();
  98.     virtual HRESULT InitDeviceObjects();
  99.     virtual HRESULT RestoreDeviceObjects();
  100.     virtual HRESULT InvalidateDeviceObjects();
  101.     virtual HRESULT DeleteDeviceObjects();
  102.     virtual HRESULT FrameMove();
  103.     virtual HRESULT Render();
  104.     virtual LRESULT MsgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  105.     virtual HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  106.     HRESULT SetFogMatrices();
  107.     HRESULT SetObjMatrices();
  108.     HRESULT LoadXFile(TCHAR*, TRIANGLESET *);
  109.     HRESULT ComputeStepTexture();
  110. };
  111.  
  112.  
  113.  
  114.  
  115. //-----------------------------------------------------------------------------
  116. // Name: WinMain()
  117. // Desc: Entry point to the program. Initializes everything, and goes into a
  118. //       message-processing loop. Idle time is used to render the scene.
  119. //-----------------------------------------------------------------------------
  120. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  121. {
  122.     CMyD3DApplication d3dApp;
  123.  
  124.     if( FAILED( d3dApp.Create( hInst ) ) )
  125.         return 0;
  126.  
  127.     return d3dApp.Run();
  128. }
  129.  
  130.  
  131.  
  132.  
  133. //-----------------------------------------------------------------------------
  134. // Name: CMyD3DApplication()
  135. // Desc: Application constructor. Sets attributes for the app.
  136. //-----------------------------------------------------------------------------
  137. CMyD3DApplication::CMyD3DApplication()
  138. {
  139.     m_bUseDepthBuffer   = TRUE;
  140.  
  141.     m_strWindowTitle    = _T("VolumeFog");
  142.  
  143.     m_pFont         = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  144.     m_pFontSmall    = new CD3DFont( _T("Arial"),  9, D3DFONT_BOLD );
  145.  
  146.     for(int i=0;i<256;i++)
  147.         m_bKey[i] = FALSE;
  148.  
  149.     D3DXMatrixIdentity(&m_matObject);
  150.     D3DXMatrixIdentity(&m_matView);
  151.     D3DXMatrixIdentity(&m_matProj);
  152.     D3DXMatrixIdentity(&m_matShadObject);
  153.  
  154.     m_vPosition      = D3DXVECTOR3( 0.0f, 0.0f,-4.0f );
  155.     m_vVelocity      = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  156.     m_fYaw           = 0.0f;
  157.     m_fYawVelocity   = 0.0f;
  158.     m_fPitch         = 0.0f;
  159.     m_fPitchVelocity = 0.0f;
  160.     m_bDrawHelp      = FALSE;
  161.    
  162.     m_pOldRenderTarget = NULL;
  163.     m_pOldStencilZ     = NULL;
  164.     m_pScreenVertBuf   = NULL;
  165.     m_pBackFogDist     = NULL;
  166.     m_pSceneDist       = NULL;
  167.     m_pTempDist        = NULL;
  168.     m_pFrontFogDist    = NULL;
  169.     m_pTargetZ         = NULL;
  170.     m_pMeshObject      = NULL;
  171.     m_pStepTexture     = NULL;
  172.     m_pCodeFogShader   = NULL;
  173.     m_pCodeFogShader2  = NULL;
  174.     m_pCodeSubPicShader= NULL;
  175.     m_pScreenVertBuf   = NULL;
  176.     m_pScreenVertBuf2  = NULL;
  177.     m_dwFogShader      = 0;
  178.     m_dwFogShader2     = 0;
  179.     m_dwSubPicShader   = 0;
  180.  
  181.     memset(&m_MeshShaderObject,0,sizeof(m_MeshShaderObject));
  182.     memset(&m_FogVolume,0,sizeof(m_FogVolume));
  183. }
  184.  
  185.  
  186.  
  187.  
  188. //-----------------------------------------------------------------------------
  189. // Name: ConfirmDevice()
  190. // Desc: Called during device intialization, this code checks the device
  191. //       for some minimum set of capabilities
  192. //-----------------------------------------------------------------------------
  193. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  194.                                           D3DFORMAT Format )
  195. {
  196.     if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
  197.         (dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
  198.     {
  199.         if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,0) )
  200.             return E_FAIL;
  201.     }
  202.           
  203.     if( pCaps->PixelShaderVersion < D3DPS_VERSION(1,1) )
  204.         return E_FAIL;
  205.     
  206.     if( dwBehavior & D3DCREATE_PUREDEVICE)
  207.         return E_FAIL;
  208.  
  209.     if( Format != D3DFMT_A8R8G8B8 && Format != D3DFMT_X8R8G8B8 && Format != D3DFMT_R8G8B8 )
  210.         return E_FAIL;
  211.   
  212.     return S_OK;
  213. }
  214.  
  215.  
  216.  
  217.  
  218. //-----------------------------------------------------------------------------
  219. // Name: MsgProc()
  220. // Desc: Process windows messages.
  221. //-----------------------------------------------------------------------------
  222. LRESULT CMyD3DApplication::MsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  223. {
  224.     switch(uMsg)
  225.     {
  226.     case WM_KEYUP:
  227.         m_bKey[wParam] = FALSE;
  228.         if( wParam == VK_F1 )
  229.             m_bDrawHelp = !m_bDrawHelp;
  230.         break;
  231.  
  232.     case WM_KEYDOWN:
  233.         m_bKey[wParam] = TRUE;
  234.         break;
  235.     }
  236.  
  237.     return CD3DApplication::MsgProc( hwnd, uMsg, wParam, lParam );
  238. }
  239.  
  240.  
  241.  
  242.  
  243. //-----------------------------------------------------------------------------
  244. // Name: ComputeStepTexture()
  245. // Desc: This computes a step texture - used for high precision fogging.  The
  246. //       step texture is a 4096 texture which incrementes from 0 to 4095. This 
  247. //       is used because on a triangle basis - the texture interpolaters are 
  248. //       much higher precision then the color interpolaters. Since we need a 
  249. //       higher precision then 8 bits, we need a way to load in more bits into
  250. //       every pixel. This is only way to do it on an 8 bit card.
  251. //-----------------------------------------------------------------------------
  252. HRESULT CMyD3DApplication::ComputeStepTexture()
  253. {
  254.     D3DLOCKED_RECT Lock;
  255.     HRESULT hr;
  256.     unsigned int Width  = 4096;
  257.     unsigned int Height = 8;
  258.     unsigned char *pLine,*pBase;
  259.     unsigned int x,y;
  260.     float widthRatio = 1.0f;
  261.     unsigned int scaledX;
  262.     
  263.     if( FAILED( hr = D3DXCreateTexture( m_pd3dDevice, Width, Height, 1, 0, D3DFMT_A8R8G8B8,
  264.         D3DPOOL_MANAGED, &m_pStepTexture ) ) )
  265.     {
  266.         return hr;
  267.     }
  268.  
  269.     // Adjust Width if D3DXCreateTexture had to pick a different texture 
  270.     // width.  Texture contents will still go up to 4096, though.
  271.     D3DSURFACE_DESC desc;
  272.     m_pStepTexture->GetLevelDesc( 0, &desc );
  273.     if( desc.Width != Width)
  274.     {
  275.         widthRatio = (float)Width / (float)desc.Width;
  276.         Width = desc.Width;
  277.     }
  278.  
  279.     if( FAILED( hr = m_pStepTexture->LockRect( 0, &Lock, NULL, 0 ) ) )
  280.     {
  281.         m_pStepTexture->Release();
  282.         return hr;
  283.     }
  284.  
  285.     pBase = (unsigned char *)Lock.pBits;
  286.  
  287.     for( y = 0; y < Height; y++ )
  288.     {
  289.         pLine = &pBase[y*Lock.Pitch];
  290.         for( x = 0; x < Width; x++ )
  291.         {
  292.             scaledX = (unsigned int)( widthRatio * (float)x );
  293.             pLine[0] =  scaledX & 0xF;  // red, lower 4 bits
  294.             pLine[2] = (scaledX & 0xFF0) >> 4; // blue, upper 8 bits
  295.             pLine[1] = 0; // green
  296.             pLine[3] = 255; // alpha
  297.             pLine += 4;
  298.         }
  299.     }
  300.  
  301.     m_pStepTexture->UnlockRect(0);
  302.     
  303.     return S_OK;
  304. }
  305.  
  306.  
  307.  
  308.  
  309. //-----------------------------------------------------------------------------
  310. // Name: LoadXFile()
  311. // Desc: This loads an xfile into the TRIANGLESET structure.  It is not enough 
  312. //       to render an X-File blindly since the the data must be fed into our 
  313. //       vertex shader.
  314. //-----------------------------------------------------------------------------
  315. HRESULT CMyD3DApplication::LoadXFile(TCHAR *pModel,TRIANGLESET *pTriSet)
  316. {
  317.     LPD3DXBUFFER pbufMaterials = NULL;    
  318.     LPD3DXBUFFER pbufAdjacency = NULL;    
  319.     LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL;
  320.     LPDIRECT3DINDEXBUFFER8 pIndexBuffer = NULL;
  321.     D3DINDEXBUFFER_DESC IndexDesc;
  322.     DWORD cMaterials;
  323.     DWORD dwDecl[100];
  324.     BYTE* pSourceI;
  325.     BYTE* pDestI;
  326.     LPD3DXMESH pMeshSysMem = NULL;
  327.     LPD3DXMESH pTempMesh = NULL;
  328.     HRESULT hr;
  329.     FILEVERTEX* pVert;
  330.     FILEVERTEX* pSource;
  331.     DWORD dwGetFVF;
  332.  
  333.     pTriSet->pVertexBuffer = NULL;
  334.     pTriSet->pIndexBuffer  = NULL;
  335.     pVertexBuffer = NULL;
  336.  
  337.     //load the x file
  338.     if( FAILED( hr = D3DXLoadMeshFromX( pModel, D3DXMESH_SYSTEMMEM, 
  339.         m_pd3dDevice, &pbufAdjacency, &pbufMaterials, &cMaterials, &pTempMesh ) ) )
  340.     {
  341.         goto FAIL;
  342.     }
  343.  
  344.     dwGetFVF = pTempMesh->GetFVF();
  345.  
  346.     // Change it to a mesh that has this vertex format if it is not that way
  347.     if(dwGetFVF != D3DFVF_FILEVERTEX)
  348.     {
  349.         D3DXDeclaratorFromFVF(D3DFVF_FILEVERTEX, dwDecl);
  350.  
  351.         hr = pTempMesh->CloneMesh(0,dwDecl,m_pd3dDevice,&pMeshSysMem);
  352.         pTempMesh->Release();
  353.         if( FAILED( hr ) )
  354.             goto FAIL;
  355.     }
  356.     else
  357.     {
  358.         pMeshSysMem = pTempMesh;
  359.     }
  360.  
  361.     pTriSet->dwNumTriangles = pMeshSysMem->GetNumFaces();
  362.     pTriSet->dwNumVertices  = pMeshSysMem->GetNumVertices();
  363.  
  364.     // Now copy the vertex buffers and index buffers into new ones that
  365.     // have things set the way we want
  366.  
  367.     if( FAILED( hr = pMeshSysMem->GetVertexBuffer( &pVertexBuffer ) ) )
  368.         goto FAIL;
  369.  
  370.     hr = m_pd3dDevice->CreateVertexBuffer( sizeof(FILEVERTEX) * pTriSet->dwNumVertices,
  371.         D3DUSAGE_WRITEONLY, D3DFVF_FILEVERTEX, D3DPOOL_MANAGED, 
  372.         &(pTriSet->pVertexBuffer ) );
  373.     if( FAILED( hr ) )
  374.         goto FAIL;
  375.  
  376.     hr = pTriSet->pVertexBuffer->Lock( 0, sizeof(FILEVERTEX)*pTriSet->dwNumVertices, (BYTE**)(&pVert), 0 );
  377.     if( FAILED( hr ) )
  378.         goto FAIL;
  379.  
  380.     hr = pVertexBuffer->Lock(0, sizeof(FILEVERTEX)*pTriSet->dwNumVertices, (BYTE**)&pSource, 0);
  381.     if( FAILED( hr ) )
  382.         goto FAIL;
  383.  
  384.     memcpy( pVert, pSource, sizeof(FILEVERTEX) * pTriSet->dwNumVertices );
  385.     
  386.     D3DXComputeBoundingSphere( pVert, pTriSet->dwNumVertices, D3DFVF_FILEVERTEX, 
  387.         &(pTriSet->Center), &(pTriSet->fRadius) );
  388.  
  389.     pVertexBuffer->Unlock();
  390.     pTriSet->pVertexBuffer->Unlock();
  391.  
  392.     if( FAILED( hr = pMeshSysMem->GetIndexBuffer( &pIndexBuffer ) ) )
  393.         goto FAIL;
  394.  
  395.     pIndexBuffer->GetDesc(&IndexDesc);
  396.  
  397.     if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer(IndexDesc.Size, D3DUSAGE_WRITEONLY, 
  398.         IndexDesc.Format, D3DPOOL_MANAGED, &(pTriSet->pIndexBuffer) ) ) )
  399.     {
  400.         goto FAIL;
  401.     }
  402.  
  403.     pIndexBuffer->Lock(0, IndexDesc.Size, &pSourceI, 0);
  404.     pTriSet->pIndexBuffer->Lock(0, IndexDesc.Size, &pDestI, 0);
  405.     memcpy(pDestI, pSourceI, IndexDesc.Size);
  406.  
  407.     pIndexBuffer->Unlock();
  408.     pTriSet->pIndexBuffer->Unlock();
  409.     
  410.     //cleanup
  411.     SAFE_RELEASE(pbufMaterials);
  412.     SAFE_RELEASE(pbufAdjacency);
  413.     SAFE_RELEASE(pMeshSysMem);
  414.     SAFE_RELEASE(pVertexBuffer);
  415.     SAFE_RELEASE(pIndexBuffer);
  416.         
  417.     return S_OK;
  418.  
  419. FAIL:
  420.     SAFE_RELEASE(pMeshSysMem);
  421.     SAFE_RELEASE(pVertexBuffer);
  422.     SAFE_RELEASE(pTriSet->pVertexBuffer);
  423.     SAFE_RELEASE(pTriSet->pIndexBuffer);
  424.     SAFE_RELEASE(pIndexBuffer);
  425.     SAFE_RELEASE(pbufMaterials);
  426.     SAFE_RELEASE(pbufAdjacency);
  427.     return hr;
  428. }
  429.  
  430.  
  431.  
  432.  
  433. //-----------------------------------------------------------------------------
  434. // Name: FrameMove()
  435. // Desc: Called once per frame, the call is the entry point for animating
  436. //       the scene.
  437. //-----------------------------------------------------------------------------
  438. HRESULT CMyD3DApplication::FrameMove()
  439. {
  440.     FLOAT fElapsedTime;
  441.  
  442.     if( m_fElapsedTime > 0.0f )
  443.         fElapsedTime = m_fElapsedTime;
  444.     else
  445.         fElapsedTime = 0.05f;
  446.  
  447.     FLOAT fSpeed        = 3.0f*fElapsedTime;
  448.     FLOAT fAngularSpeed = 1.0f*fElapsedTime;
  449.  
  450.     // De-accelerate the camera movement (for smooth motion)
  451.     m_vVelocity      *= 0.9f;
  452.     m_fYawVelocity   *= 0.9f;
  453.     m_fPitchVelocity *= 0.9f;
  454.  
  455.     // Process keyboard input
  456.     if( m_bKey[VK_RIGHT] )    m_vVelocity.x    += fSpeed; // Slide Right
  457.     if( m_bKey[VK_LEFT] )     m_vVelocity.x    -= fSpeed; // Slide Left
  458.     if( m_bKey[VK_UP] )       m_vVelocity.y    += fSpeed; // Slide Up
  459.     if( m_bKey[VK_DOWN] )     m_vVelocity.y    -= fSpeed; // Slide Down
  460.     if( m_bKey['W'] )         m_vVelocity.z    += fSpeed; // Move Forward
  461.     if( m_bKey['S'] )         m_vVelocity.z    -= fSpeed; // Move Backward
  462.     if( m_bKey['E'] )         m_fYawVelocity   += fSpeed; // Turn Right
  463.     if( m_bKey['Q'] )         m_fYawVelocity   -= fSpeed; // Turn Left
  464.     if( m_bKey['Z'] )         m_fPitchVelocity += fSpeed; // Turn Down
  465.     if( m_bKey['A'] )         m_fPitchVelocity -= fSpeed; // Turn Up
  466.  
  467.     // Update the position vector
  468.     D3DXVECTOR3 vT = m_vVelocity * fSpeed;
  469.     D3DXVec3TransformNormal( &vT, &vT, &m_matOrientation );
  470.     m_vPosition += vT;
  471.  
  472.     // Update the yaw-pitch-rotation vector
  473.     m_fYaw   += fAngularSpeed * m_fYawVelocity;
  474.     m_fPitch += fAngularSpeed * m_fPitchVelocity;
  475.  
  476.     // Set the view matrix
  477.     D3DXQUATERNION qR;
  478.     D3DXQuaternionRotationYawPitchRoll( &qR, m_fYaw, m_fPitch, 0.0f );
  479.     D3DXMatrixAffineTransformation( &m_matOrientation, 1.25f, NULL, &qR, &m_vPosition );
  480.     D3DXMatrixInverse( &m_matView, NULL, &m_matOrientation );
  481.     return S_OK;
  482. }
  483.  
  484.  
  485.  
  486.  
  487. //-----------------------------------------------------------------------------
  488. // Name: SetFogMatrices()
  489. // Desc: Sets up the fog matrices, the matrices which represnet the fog volume's 
  490. //       position.  These have to be loaded into the right places in the vertex 
  491. //       shader:
  492. //       0-3 = object transformat matrix
  493. //       16-19 = ObjectView
  494. //       8-11 = Total matrix
  495. //-----------------------------------------------------------------------------
  496. HRESULT CMyD3DApplication::SetFogMatrices()
  497. {
  498.     D3DXMATRIX  temp,tObject,m_matTot;
  499.     
  500.     D3DXMatrixMultiply(&m_matTot,  &m_matObject,&m_matView);
  501.     D3DXMatrixTranspose(&temp,&m_matTot);
  502.     m_pd3dDevice->SetVertexShaderConstant( 16,&temp, 4 );
  503.   
  504.     D3DXMatrixMultiply(&m_matTot,&m_matTot,&m_matProj);
  505.  
  506.     D3DXMatrixTranspose(&m_matTot,&m_matTot);
  507.     D3DXMatrixTranspose(&tObject,&m_matObject);
  508.  
  509.     //these need to be tranposes
  510.     m_pd3dDevice->SetVertexShaderConstant( 0, &tObject, 4 );
  511.     m_pd3dDevice->SetVertexShaderConstant( 8, &m_matTot, 4 );
  512.  
  513.     //the w clip distance
  514.  
  515.     return S_OK;
  516. }
  517.  
  518.  
  519.  
  520.  
  521. //-----------------------------------------------------------------------------
  522. // Name: SetObjMatrices()
  523. // Desc: Sets up the objects matrices, the matrices which represent the object 
  524. //       (or the world) volume's position.  These have to be loaded into the 
  525. //       right places in the vertex shader:
  526. //       0-3 = object transformation matrix
  527. //       16-19 = ObjectView
  528. //-----------------------------------------------------------------------------
  529. HRESULT CMyD3DApplication::SetObjMatrices()
  530. {
  531.     D3DXMATRIX  temp,tObject,m_matTot;
  532.     
  533.     D3DXMatrixTranspose(&tObject,&m_matShadObject);
  534.     m_pd3dDevice->SetVertexShaderConstant( 0, &tObject, 4 );
  535.  
  536.     D3DXMatrixMultiply(&m_matTot, &m_matShadObject,&m_matView);
  537.     D3DXMatrixTranspose(&temp,&m_matTot);
  538.     m_pd3dDevice->SetVertexShaderConstant( 16, &temp, 4 );
  539.   
  540.     D3DXMatrixMultiply(&m_matTot,&m_matTot,&m_matProj);
  541.  
  542.     D3DXMatrixTranspose(&m_matTot,&m_matTot);
  543.     m_pd3dDevice->SetVertexShaderConstant( 8, &m_matTot, 4 );
  544.  
  545.     return S_OK;
  546. }
  547.  
  548.  
  549.  
  550.  
  551. //-----------------------------------------------------------------------------
  552. // Name: Render()
  553. // Desc: Called once per frame, the call is the entry point for 3d
  554. //       rendering. This function sets up render states, clears the
  555. //       viewport, and renders the scene.
  556. //-----------------------------------------------------------------------------
  557. HRESULT CMyD3DApplication::Render()
  558. {
  559.     D3DXVECTOR3 lightDir(1,0,0);
  560.     D3DXVECTOR3 sub;
  561.     D3DXVECTOR4 WClip;
  562.  
  563.     HRESULT hr;
  564.     D3DXMATRIX  temp,tObject,m_matTot;
  565.     LPDIRECT3DSURFACE8 pSurface;
  566.     D3DMATERIAL8 Mat;
  567.         
  568.     D3DVIEWPORT8 ViewPort,OldPort;
  569.     VOID* pVerts;
  570.     D3DLIGHT8 myLight;
  571.  
  572.     //WClip represents our near and far fog 'clipping' (the y index is the inverse of the rear
  573.     //clipping plane)
  574.     //planes. The higher precision one has a further clipping plane 
  575.  
  576.     WClip = D3DXVECTOR4(1,.015f,1,1);
  577.     
  578.     // Compute the current viewport
  579.     // Since we might be on a pure device, we can't query it from the driver
  580.     OldPort.X = 0;
  581.     OldPort.Y = 0;
  582.     OldPort.Width = m_d3dsdBackBuffer.Width;
  583.     OldPort.Height = m_d3dsdBackBuffer.Height;
  584.     OldPort.MaxZ = 1;
  585.     OldPort.MinZ = 0;  
  586.  
  587.     FLOAT fAspectRatio = (FLOAT)OldPort.Width / (FLOAT) OldPort.Height;
  588.  
  589.     D3DXMATRIX  mat1,mat2;
  590.  
  591.     // Update projection matrix for a changed aspect ratio
  592.     D3DXMatrixPerspectiveFovLH(&m_matProj, 0.75f, fAspectRatio, 1.0f, 100);
  593.  
  594.     lightDir = D3DXVECTOR3(2.5f, 2.25f, -2.55f);
  595.  
  596.     // Set up a set of points which represents the screen
  597.     static struct { FLOAT x,y,z,w; DWORD color; FLOAT u,v; } s_Verts[] =
  598.     {
  599.         {1.0f,   1.0f, 0.5f, 1.0f , D3DCOLOR_XRGB( 0xff, 0xff, 0x8f ), 1,0 },
  600.         {1.0f, -1.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0xff, 0xff, 0x8f),  1,1},
  601.         { -1.0f, 1.0f, 0.5f, 1.0f,   D3DCOLOR_XRGB( 0xff, 0xff, 0x8f),  0,0},
  602.         { -1.0f,  -1.0f, 0.5f, 1.0f,  D3DCOLOR_XRGB( 0xff, 0xff, 0x8f),  0,1},
  603.     };
  604.      
  605.     if( FAILED( hr = m_pScreenVertBuf->Lock( 0, sizeof(s_Verts), (BYTE **)(&pVerts), 0 ) ) )
  606.         goto FAIL;
  607.     
  608.     memcpy( (void*)pVerts, (void*)s_Verts, sizeof(s_Verts) );
  609.     
  610.     if( FAILED( hr = m_pScreenVertBuf->Unlock() ) )
  611.         goto FAIL;
  612.  
  613.     //set the fog clipping into the vertex shader's constant register #12
  614.     m_pd3dDevice->SetVertexShaderConstant( 12, &WClip, 1 );
  615.     
  616.     m_pd3dDevice->BeginScene();
  617.  
  618.     //now we render the first half of the fog scene - or rather, the back side of the 
  619.     //fog. what will be left in the buffer after we are done is the w depth of the 
  620.     //back fog volume 
  621.  
  622.     ViewPort.X = 0;
  623.     ViewPort.Y = 0;
  624.     ViewPort.Height = RENDERTARGSIZE;
  625.     ViewPort.Width =  RENDERTARGSIZE;
  626.     ViewPort.MaxZ = 1;
  627.     ViewPort.MinZ = 0;
  628.      
  629.     if( FAILED( hr = m_pScreenVertBuf2->Lock( 0, sizeof(s_Verts), (BYTE **)(&pVerts), 0 ) ) )
  630.         goto FAIL;
  631.     
  632.     memcpy( (void*)pVerts, (void*)s_Verts, sizeof(s_Verts) );
  633.     
  634.     if (FAILED(hr = m_pScreenVertBuf2->Unlock()) )
  635.         goto FAIL;
  636.  
  637.     m_pd3dDevice->SetTexture(0,NULL);
  638.     m_pd3dDevice->SetTexture(1,NULL);
  639.     m_pd3dDevice->SetTexture(2,NULL);
  640.     m_pd3dDevice->SetTexture(3,NULL);
  641.  
  642.     m_pd3dDevice->SetPixelShader(0);
  643.         
  644.     //we will just use a special vertex shader to fill the color and alpha as our w depth using the
  645.     //step texture
  646.     m_pd3dDevice->SetRenderState(D3DRS_WRAP0, 0 );
  647.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  648.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  649.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  650.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  651.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  652.     m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0x01010101);
  653.  
  654.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
  655.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
  656.  
  657.    //use our step texture to get higher precision interpolating
  658.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  659.         
  660.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  661.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  662.     
  663.     m_pd3dDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
  664.     m_pd3dDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
  665.  
  666.     m_pd3dDevice->SetTexture(0,m_pStepTexture);
  667.     m_pd3dDevice->SetTexture(1,NULL);
  668.       
  669.     //set up tranform matrices for the fixed pipe.
  670.     //this only used for the rendering of the object
  671.     m_pd3dDevice->SetTransform(D3DTS_VIEW,&m_matView);
  672.     m_pd3dDevice->SetTransform(D3DTS_PROJECTION,&m_matProj );
  673.     m_pd3dDevice->SetTransform(D3DTS_WORLD,&m_matObject);
  674.  
  675.     //Now we need to draw the scene, happens first to also set the Z 
  676.     hr =  m_pSceneDist->GetSurfaceLevel(0, &pSurface);
  677.     
  678.     //first, render the scene with the depth encoding
  679.     hr =  m_pd3dDevice->SetRenderTarget(pSurface, m_pTargetZ);
  680.     m_pd3dDevice->SetViewport(&ViewPort);
  681.     hr =  m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ,
  682.                                  D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
  683.  
  684.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 
  685.  
  686.     SetObjMatrices();
  687.     m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x00000000);
  688.     m_pd3dDevice->SetIndices(m_MeshShaderObject.pIndexBuffer, 0);
  689.     m_pd3dDevice->SetStreamSource( 0,m_MeshShaderObject.pVertexBuffer, sizeof(FILEVERTEX) );
  690.     m_pd3dDevice->SetVertexShader(m_dwFogShader);
  691.  
  692.     //no alpha blending since geometry is opaque
  693.     m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  694.     m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  695.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);  
  696.     hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
  697.         m_MeshShaderObject.dwNumVertices, 0, m_MeshShaderObject.dwNumTriangles);
  698.  
  699.     //Now Render the back side of the fog, the
  700.     //z buffer is the same as the one set by the geometry
  701.     //since elements of the fog behind the scene should not be rendered (sine they are not visible)
  702.     pSurface->Release();
  703.     hr = m_pBackFogDist->GetSurfaceLevel(0,&pSurface);
  704.     hr = m_pd3dDevice->SetRenderTarget(pSurface,m_pTargetZ);
  705.     hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
  706.     
  707.     SetFogMatrices();
  708.  
  709.     //reverse the culling order to get the back side
  710.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  711.     
  712.     //add up all the backsides, this is volumetric rendering so 
  713.     //everythin is totally transparent, want to check Z Buffer,
  714.     //but not write to it.
  715.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);   
  716.     m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE); 
  717.     m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  718.     m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  719.     m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  720.  
  721.     //the tfactor adds in the alpha so that we can keep track the number
  722.     //of times a pixel is in and out of a fog
  723.     m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x10101010);
  724.     m_pd3dDevice->SetIndices(m_FogVolume.pIndexBuffer, 0);
  725.     m_pd3dDevice->SetStreamSource( 0, m_FogVolume.pVertexBuffer, sizeof(FILEVERTEX) );
  726.     m_pd3dDevice->SetVertexShader(m_dwFogShader);
  727.     hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,
  728.         m_FogVolume.dwNumVertices, 0, m_FogVolume.dwNumTriangles );
  729.     pSurface->Release();
  730.  
  731.     //Now we need to draw the front end of the fog
  732.     //same concept as above, but htis time the front haves of the 
  733.     //fog get drawned
  734.     hr =  m_pFrontFogDist->GetSurfaceLevel(0, &pSurface);
  735.     hr =  m_pd3dDevice->SetRenderTarget(pSurface, m_pTargetZ);
  736.     m_pd3dDevice->SetViewport(&ViewPort);
  737.     hr =  m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET  ,
  738.                                  D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
  739.  
  740.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);   
  741.     m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,FALSE);  
  742.     m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x10101010);
  743.     m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);//DESTALPHA);
  744.     m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  745.     m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  746.     m_pd3dDevice->SetVertexShaderConstant(0, &tObject, 4);
  747.     m_pd3dDevice->SetVertexShaderConstant(8, &m_matTot, 4);
  748.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 
  749.  
  750.     SetFogMatrices();
  751.     m_pd3dDevice->SetIndices(m_FogVolume.pIndexBuffer, 0);
  752.     m_pd3dDevice->SetStreamSource( 0, m_FogVolume.pVertexBuffer, sizeof(FILEVERTEX) );
  753.     m_pd3dDevice->SetVertexShader(m_dwFogShader);
  754.     hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
  755.         m_FogVolume.dwNumVertices, 0, m_FogVolume.dwNumTriangles);
  756.     pSurface->Release();
  757.  
  758.     //first we render the object, or whatever solid objects
  759.     //we have in the scene. This will act as the back side of our
  760.     //fog if it happens to be in the fog volume
  761.  
  762.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);   
  763.     m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE);  
  764.    
  765.     m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  766.     m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  767.     m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  768.  
  769.     //now we are ready to actually draw the scene
  770.     m_pd3dDevice->SetRenderTarget(m_pOldRenderTarget, m_pOldStencilZ);
  771.     m_pd3dDevice->SetViewport(&OldPort);
  772.  
  773.     hr =  m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ,
  774.                                   D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
  775.  
  776.     //first draw the scene as it is.
  777.     m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView);
  778.     m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProj );
  779.     m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matShadObject);
  780.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  781.    
  782.     memset(&Mat,0,sizeof(Mat));
  783.  
  784.     //generic light and generic scene.
  785.     myLight.Type = D3DLIGHT_DIRECTIONAL;
  786.     myLight.Diffuse.r = 0;
  787.     myLight.Diffuse.g = 1;
  788.     myLight.Diffuse.b = 0;
  789.     myLight.Diffuse.a = 1;
  790.     myLight.Range     = 1000000;
  791.     myLight.Direction = D3DXVECTOR3(1,1,1);
  792.     
  793.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  794.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  795.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  796.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  797.  
  798.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  799.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  800.     
  801.     m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
  802.     m_pd3dDevice->LightEnable(0, TRUE);
  803.  
  804.     m_pd3dDevice->SetLight(0, &myLight);
  805.     
  806.     Mat.Diffuse.r = 1;
  807.     Mat.Diffuse.b = 1;
  808.     Mat.Diffuse.g = 1;
  809.     Mat.Diffuse.a = 1;
  810.  
  811.     m_pd3dDevice->SetMaterial(&Mat);
  812.     
  813.     m_pd3dDevice->SetTexture(0, NULL);
  814.     m_pd3dDevice->SetTexture(1, NULL);
  815.  
  816.     D3DVERTEXBUFFER_DESC vDesc;
  817.     m_MeshShaderObject.pVertexBuffer->GetDesc(&vDesc);
  818.     m_pd3dDevice->SetStreamSource( 0,m_MeshShaderObject.pVertexBuffer, sizeof(FILEVERTEX) );
  819.     m_pd3dDevice->SetIndices(m_MeshShaderObject.pIndexBuffer, 0);
  820.     m_pd3dDevice->SetVertexShader(D3DFVF_FILEVERTEX);
  821.     hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
  822.         m_MeshShaderObject.dwNumVertices, 0, m_MeshShaderObject.dwNumTriangles);
  823.  
  824.     m_pd3dDevice->SetTexture(0, NULL);
  825.     m_pd3dDevice->SetTexture(1, NULL);
  826.     m_pd3dDevice->SetTexture(2, NULL);
  827.     m_pd3dDevice->SetTexture(3, NULL);
  828.  
  829.     //draw the fog
  830.     //this uses a complex pixel shader which is fully commented
  831.     //this computes the amount of fog at every pixel on the screen
  832.  
  833.     m_pd3dDevice->SetRenderTarget(m_pOldRenderTarget, m_pOldStencilZ);
  834.     m_pd3dDevice->SetViewport(&OldPort);
  835.  
  836.     m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  837.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 
  838.   
  839.     m_pd3dDevice->SetRenderState(D3DRS_WRAP0, 0);
  840.     m_pd3dDevice->SetRenderState(D3DRS_WRAP1, 0);
  841.     m_pd3dDevice->SetRenderState(D3DRS_WRAP2, 0);
  842.  
  843.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
  844.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
  845.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  846.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
  847.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
  848.  
  849.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_POINT );
  850.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_POINT );
  851.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  852.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
  853.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
  854.  
  855.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_POINT );
  856.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_POINT );
  857.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  858.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
  859.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
  860.  
  861.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
  862.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 0 );
  863.     
  864.     m_pd3dDevice->SetPixelShader(m_dwSubPicShader);
  865.     m_pd3dDevice->SetTexture(0,m_pFrontFogDist);
  866.     m_pd3dDevice->SetTexture(1,m_pBackFogDist);
  867.     m_pd3dDevice->SetTexture(2,m_pSceneDist);
  868.     
  869.     //alpha blend on. If we want to do volumetric light, we use an additive rather
  870.     //then blended mode
  871.     m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);   
  872.     m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  873.     m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  874.  
  875.  
  876.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  877.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 2 );
  878.  
  879.     //simple vertex shader, just copies coordinates and stuff.
  880.     m_pd3dDevice->SetVertexShader(m_dwFogShader2);
  881.     m_pd3dDevice->SetStreamSource( 0, m_pScreenVertBuf, 7 * sizeof(FLOAT) );
  882.     m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  883.  
  884.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);   
  885.  
  886.     // Output statistics
  887.     m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  888.     m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  889.     
  890.     // Draw help
  891.     if( m_bDrawHelp )
  892.     {
  893.         m_pFontSmall->DrawText( 2, 40, 0xffffff00,
  894.                                 _T("Keyboard controls:") );
  895.         m_pFontSmall->DrawText( 20, 60, 0xffffff00,
  896.                                 _T("Move\nTurn\nPitch\nSlide\n\nHelp\n"
  897.                                    "Change device\n"
  898.                                    "Exit") );
  899.         m_pFontSmall->DrawText( 160, 60, 0xffffff00,
  900.                                 _T("W,S\nE,Q\nA,Z\nArrow keys\n\n"
  901.                                    "F1\nF2\nEsc") );
  902.     }
  903.     else
  904.     {
  905.         m_pFontSmall->DrawText( 2, 40, 0xffffff00, _T("Press F1 for help") );
  906.     }
  907.  
  908.     m_pd3dDevice->EndScene();
  909.  
  910.     return S_OK;
  911.  
  912. FAIL:
  913.     return hr;
  914. }
  915.  
  916.  
  917.  
  918.  
  919. //-----------------------------------------------------------------------------
  920. // Name: InitDeviceObjects()
  921. // Desc: Initialize scene objects.
  922. //-----------------------------------------------------------------------------
  923. HRESULT CMyD3DApplication::InitDeviceObjects()
  924. {
  925.     TCHAR model[160];
  926.     TCHAR model2[160];
  927.     HRESULT hr;
  928.  
  929.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  930.     m_pFontSmall->InitDeviceObjects( m_pd3dDevice );
  931.  
  932.     if( FAILED( hr = DXUtil_FindMediaFile( model, _T("fog2.x") ) ) )
  933.         return D3DAPPERR_MEDIANOTFOUND;
  934.     if( FAILED( hr = DXUtil_FindMediaFile( model2, _T("room2.x") ) ) )
  935.         return D3DAPPERR_MEDIANOTFOUND;
  936.   
  937.     if( D3DSHADER_VERSION_MAJOR( m_d3dCaps.PixelShaderVersion ) >= 1 )
  938.         m_bUsePicShader = TRUE;
  939.     else
  940.         m_bUsePicShader = FALSE;
  941.  
  942.     if( FAILED( hr = LoadXFile( model, &m_FogVolume ) ) )
  943.         return hr;
  944.  
  945.     if( FAILED( hr = LoadXFile( model2, &m_MeshShaderObject ) ) )
  946.         return hr;
  947.  
  948.     if( FAILED( hr = D3DXLoadMeshFromX( model2, D3DXMESH_SYSTEMMEM, m_pd3dDevice, 
  949.         NULL, NULL, NULL, &m_pMeshObject ) ) )
  950.     {
  951.         return hr;
  952.     }
  953.  
  954.     if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 7 * sizeof(FLOAT) * 4, 0,
  955.         D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &m_pScreenVertBuf ) ) )
  956.     {
  957.         return hr;
  958.     }
  959.     
  960.     if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 7 * sizeof(FLOAT) * 4, 0,
  961.         D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &m_pScreenVertBuf2 ) ) )
  962.     {
  963.         return hr;
  964.     }
  965.  
  966.     if( FAILED( hr = ComputeStepTexture() ) )
  967.         return hr;
  968.  
  969.     TCHAR FogShader1[160];
  970.     TCHAR SubtractShader[160];
  971.     if( FAILED( hr = DXUtil_FindMediaFile( FogShader1, _T("fogshader.vsh") ) ) )
  972.         return D3DAPPERR_MEDIANOTFOUND;
  973.     if( FAILED( hr = DXUtil_FindMediaFile( SubtractShader, _T("FogPixShader.psh") ) ) )
  974.         return D3DAPPERR_MEDIANOTFOUND;
  975.   
  976.     if( FAILED( hr = D3DXAssembleShaderFromFile(FogShader1, 0, NULL, &m_pCodeFogShader, NULL ) ) )
  977.        return hr;
  978.     
  979.     if( FAILED( hr = DXUtil_FindMediaFile( FogShader1, _T("fogshader2.vsh") ) ) )
  980.         return D3DAPPERR_MEDIANOTFOUND;
  981.     if( FAILED( hr = D3DXAssembleShaderFromFile(FogShader1, 0, NULL, &m_pCodeFogShader2, NULL ) ) )
  982.        return hr;
  983.   
  984.     if( FAILED( hr = DXUtil_FindMediaFile( SubtractShader, _T("FogPixShader.psh") ) ) )
  985.         return D3DAPPERR_MEDIANOTFOUND;
  986.     if( FAILED( hr = D3DXAssembleShaderFromFile(SubtractShader, 0, NULL, &m_pCodeSubPicShader, NULL ) ) )
  987.         return hr;
  988.  
  989.     return S_OK;
  990. }
  991.  
  992.  
  993.  
  994.  
  995. //-----------------------------------------------------------------------------
  996. // Name: RestoreDeviceObjects()
  997. // Desc: Initialize scene objects.
  998. //-----------------------------------------------------------------------------
  999. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  1000. {
  1001.     HRESULT hr;
  1002.     
  1003.     m_pFont->RestoreDeviceObjects();
  1004.     m_pFontSmall->RestoreDeviceObjects();
  1005.  
  1006.     DWORD dwDecl[] = 
  1007.     {
  1008.         D3DVSD_STREAM(0),
  1009.         D3DVSD_REG(0,   D3DVSDT_FLOAT3),
  1010.         D3DVSD_REG(1,   D3DVSDT_FLOAT3),
  1011.         D3DVSD_END()
  1012.     };
  1013.      
  1014.     DWORD dwDecl2[] = 
  1015.     {
  1016.         D3DVSD_STREAM(0),
  1017.         D3DVSD_REG(0, D3DVSDT_FLOAT4),
  1018.         D3DVSD_REG(5, D3DVSDT_D3DCOLOR),
  1019.         D3DVSD_REG(7, D3DVSDT_FLOAT2),
  1020.         D3DVSD_END()
  1021.     };
  1022.     
  1023.     if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
  1024.         D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pBackFogDist ) ) )
  1025.     {
  1026.         return hr;
  1027.     }
  1028.  
  1029.     if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
  1030.         D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pFrontFogDist ) ) )
  1031.     {
  1032.         return hr;
  1033.     }
  1034.  
  1035.     if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
  1036.         D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSceneDist ) ) )
  1037.     {
  1038.         return hr;
  1039.     }
  1040.  
  1041.     if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
  1042.         D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pTempDist ) ) )
  1043.     {
  1044.         return hr;
  1045.     }
  1046.  
  1047.     if( FAILED( hr = m_pd3dDevice->CreateDepthStencilSurface( RENDERTARGSIZE,RENDERTARGSIZE,
  1048.         D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_pTargetZ ) ) )
  1049.     {
  1050.         return hr;
  1051.     }
  1052.  
  1053.     m_dwFogShader = 0;
  1054.     if (FAILED( hr = m_pd3dDevice->CreateVertexShader( dwDecl,
  1055.         (DWORD*)m_pCodeFogShader->GetBufferPointer(), &m_dwFogShader, 0 ) ) )
  1056.     {
  1057.         return hr;
  1058.     }
  1059.  
  1060.     m_dwFogShader2 = 0;
  1061.     if (FAILED( hr = m_pd3dDevice->CreateVertexShader( dwDecl2,
  1062.         (DWORD*)m_pCodeFogShader2->GetBufferPointer(), &m_dwFogShader2, 0 ) ) )
  1063.     {
  1064.         return hr;
  1065.     }
  1066.         
  1067.     m_dwSubPicShader = 0;
  1068.     if (FAILED( hr = m_pd3dDevice->CreatePixelShader( (DWORD*)m_pCodeSubPicShader->GetBufferPointer(),
  1069.         &m_dwSubPicShader ) ) )
  1070.     {
  1071.         return hr;
  1072.     }
  1073.  
  1074.     if( FAILED( hr = m_pd3dDevice->GetRenderTarget( &m_pOldRenderTarget ) ) )
  1075.         return hr;
  1076.  
  1077.     if( FAILED( hr = m_pd3dDevice->GetDepthStencilSurface( &m_pOldStencilZ ) ) )
  1078.         return hr;
  1079.  
  1080.     return S_OK;
  1081. }
  1082.  
  1083.  
  1084.  
  1085.  
  1086. //-----------------------------------------------------------------------------
  1087. // Name: InvalidateDeviceObjects()
  1088. // Desc:
  1089. //-----------------------------------------------------------------------------
  1090. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  1091. {
  1092.     m_pFont->InvalidateDeviceObjects();
  1093.     m_pFontSmall->InvalidateDeviceObjects();
  1094.  
  1095.     SAFE_RELEASE(m_pOldRenderTarget);
  1096.     SAFE_RELEASE(m_pOldStencilZ);
  1097.     SAFE_RELEASE(m_pFrontFogDist);
  1098.     SAFE_RELEASE(m_pBackFogDist);
  1099.     SAFE_RELEASE(m_pSceneDist);
  1100.     SAFE_RELEASE(m_pTempDist);
  1101.     SAFE_RELEASE(m_pTargetZ);
  1102.     if( m_dwSubPicShader != 0 )
  1103.     {
  1104.         m_pd3dDevice->DeletePixelShader(m_dwSubPicShader);
  1105.         m_dwSubPicShader = 0;
  1106.     }
  1107.     if( m_dwFogShader != 0 )
  1108.     {
  1109.         m_pd3dDevice->DeleteVertexShader(m_dwFogShader);
  1110.         m_dwFogShader = 0;
  1111.     }
  1112.     if( m_dwFogShader2 != 0 )
  1113.     {
  1114.         m_pd3dDevice->DeleteVertexShader(m_dwFogShader2);
  1115.         m_dwFogShader2 = 0;
  1116.     }
  1117.     return S_OK;
  1118. }
  1119.  
  1120.  
  1121. //-----------------------------------------------------------------------------
  1122. // Name: DeleteDeviceObjects()
  1123. // Desc: Called when the app is exiting, or the device is being changed,
  1124. //       this function deletes any device dependent objects.
  1125. //-----------------------------------------------------------------------------
  1126. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  1127. {
  1128.     m_pFont->DeleteDeviceObjects();
  1129.     m_pFontSmall->DeleteDeviceObjects();
  1130.     SAFE_RELEASE(m_pScreenVertBuf);
  1131.     SAFE_RELEASE(m_pScreenVertBuf2);
  1132.     SAFE_RELEASE(m_FogVolume.pVertexBuffer);
  1133.     SAFE_RELEASE(m_FogVolume.pIndexBuffer);
  1134.     SAFE_RELEASE(m_MeshShaderObject.pVertexBuffer);
  1135.     SAFE_RELEASE(m_MeshShaderObject.pIndexBuffer);
  1136.     SAFE_RELEASE(m_pMeshObject);
  1137.     SAFE_RELEASE(m_pStepTexture);
  1138.     SAFE_RELEASE(m_pCodeFogShader);
  1139.     SAFE_RELEASE(m_pCodeSubPicShader);
  1140.     SAFE_RELEASE(m_pCodeFogShader2);
  1141.  
  1142.     return S_OK;
  1143. }
  1144.